#include "ms1022.h"
#include "stm32f4xx_hal.h"
#include "main.h"
#include "Utility.h"
#include "DBG.h"

#define MS1022_SCK_L			HAL_GPIO_WritePin(TDC_SCK_GPIO_Port,TDC_SCK_Pin,GPIO_PIN_RESET)
#define MS1022_SCK_H			HAL_GPIO_WritePin(TDC_SCK_GPIO_Port,TDC_SCK_Pin,GPIO_PIN_SET)
#define MS1022_SI_L				HAL_GPIO_WritePin(TDC_SI_GPIO_Port,TDC_SI_Pin,GPIO_PIN_RESET)
#define MS1022_SI_H				HAL_GPIO_WritePin(TDC_SI_GPIO_Port,TDC_SI_Pin,GPIO_PIN_SET)
#define MS1022_SO				(TDC_SO_GPIO_Port->IDR & TDC_SO_Pin)
#define MS1022_INT			(TDC_INT_GPIO_Port->IDR & TDC_INT_Pin)
#define MS1022_SSN_L			HAL_GPIO_WritePin(TDC_CS_GPIO_Port,TDC_CS_Pin,GPIO_PIN_RESET)
#define MS1022_SSN_H			HAL_GPIO_WritePin(TDC_CS_GPIO_Port,TDC_CS_Pin,GPIO_PIN_SET)

static void SPI_Enable(void)
{
	MS1022_SSN_L;	// followed by 40ns at least
}

static void SPI_Disable(void)
{	
	MS1022_SSN_H;	// followed by 50ns at least
}

void SPI_WriteCommand(uint8_t wbuf8)
{
	uint8_t cnt, tmp;
	tmp = 0x80;
    MS1022_SCK_L;
 	SPI_Enable();
 	for(cnt=8; cnt>0; cnt--)
    {
        MS1022_SCK_H;
    	if((wbuf8&tmp) == 0)
       		MS1022_SI_L;
     	else
       		MS1022_SI_H;
     	MS1022_SCK_L;
     	tmp = tmp >> 1;
    }
    SPI_Disable();
}

void SPI_WriteCommands(uint32_t wbuf8, uint8_t len)
{
	uint8_t cnt, tmp;
	tmp = 0x80;
    MS1022_SCK_L;
 	SPI_Enable();
 	for(cnt=8; cnt>0; cnt--)
    {
        MS1022_SCK_H;
    	if((wbuf8&tmp) == 0)
       		MS1022_SI_L;
     	else
       		MS1022_SI_H;
     	MS1022_SCK_L;
     	tmp = tmp >> 1;
    }
    SPI_Disable();
}

void SPI_WriteRegister(uint32_t reg, uint8_t address)
{
	uint8_t cmd = 0x80 | address;
	uint8_t cnt;
 	uint32_t tmp;
 	
 	tmp = 0x80000000;
    
    //printf("cmd= %x\n",cmd);
 	SPI_Enable();
	for(int i=0; i<8;i++)
	{
			MS1022_SCK_H;
			if(cmd & 0x80)
			{
					MS1022_SI_H;
			}
			else
			{
					MS1022_SI_L;
			}
			MS1022_SCK_L;
			cmd = cmd << 1;
	}
 	for(cnt=32; cnt>0; cnt--)
	{
			MS1022_SCK_H;
		if((reg&tmp) == 0)
				MS1022_SI_L;
		else
				MS1022_SI_H;
			MS1022_SCK_L;
		tmp = tmp >> 1;
	}
	SPI_Disable();
}

uint16_t SPI_ReadStatus(uint8_t cmd)
{
	uint16_t rbuf32;	
 	uint8_t cnt, tmp8;
 	uint16_t tmp32;
 	
 	tmp8 = 0x80;
 	SPI_Enable();
 	for(cnt=8; cnt>0; cnt--)
    {
        MS1022_SCK_H;
    	if((cmd&tmp8) == 0)
       		MS1022_SI_L;
     	else
       		MS1022_SI_H;
     	MS1022_SCK_L;
     	tmp8 = tmp8 >> 1;
    }
    
    tmp32 = 0x8000;
    rbuf32 = 0x00000000;
 	for(cnt=16; cnt>0; cnt--)
    {
    	MS1022_SCK_H;
        //UTIL_IdleCycle(5);
        MS1022_SCK_L;
    	if(MS1022_SO)
        	rbuf32 |= tmp32;
     	tmp32 = tmp32 >> 1;
    }
    SPI_Disable();
 	return(rbuf32);
}

uint32_t SPI_ReadReg(uint8_t cmd)
{
	uint32_t rbuf32;
 	uint8_t cnt, tmp8;
 	uint32_t tmp32;
 	
 	tmp8 = 0x80;
 	SPI_Enable();
 	for(cnt=8; cnt>0; cnt--)
    {
        MS1022_SCK_H;
    	if((cmd&tmp8) == 0)
       		MS1022_SI_L;
     	else
       		MS1022_SI_H;
     	MS1022_SCK_L;
     	tmp8 = tmp8 >> 1;
    }
    
    tmp32 = 0x80000000;
    rbuf32 = 0x00000000;
 	for(cnt=32; cnt>0; cnt--)
    {
    	MS1022_SCK_H;
        MS1022_SCK_L;
    	if(MS1022_SO)
        	rbuf32 |= tmp32;
     	tmp32 = tmp32 >> 1;
    }
    SPI_Disable();
 	
	return(rbuf32);
}


void MS1022_Init(void)
{
    MS1022_SSN_H;
    MS1022_SCK_L;

    SPI_WriteCommand(0x50);
    delay_ms(100);
    //reg0 4-6(110) 8-11(10) 14-16(1)
    //测量范围2(11,1),自动校准(12,0),校准开启(13,1),晶振一直开启(1,18),HCLK不分频(20,0),内部时钟分频3(24,2)
    uint32_t value = (1<<11) | (1<<13) | (1<<18) | (0<<20) | (2<<24) | 0xAB;
	  //value = 0x80020668<<8;
    SPI_WriteRegister(value, 0);
    //32k高电流(15,1),HIT1 2个脉冲, 默认值(22,1), 0x21自校准开启,应该用不到
    value = (1<<15) | (2<<16) | (1<<22) | (0x21<<24) | 0xCD;
	  //value = 0x81214280<<8;
    SPI_WriteRegister(value, 1);
    //超时和alu中断
    value = (1u<<29) | 0xEF ;
	  //value = 0x82200000<<8;
    SPI_WriteRegister(value, 2);
    //EN_AUTOCALC_MB2(31,1),EN_ERR_VAL(29,1), SEL_TIMO_MB2(27,3)
    value = (3u<<27) | (1u<<29) | (1u<<31);
    SPI_WriteRegister(value, 3);
    SPI_WriteRegister(0x20000000, 4);
    //噪声单元,先关闭
    value = (0<<28);
		
    SPI_WriteRegister(value, 5);
    //开启4倍精度模式
    value = (0<<13);
		//value = 0x86002020<<8;
    SPI_WriteRegister(value, 6);
    uint32_t tmp = SPI_ReadReg(0xB7);
		if(tmp != 0xABCDEF00)
		{
			printf("MS1022 init failed 0xb7 = %x expect= %x\n",tmp, 0xABCDEF00);
		}
		else {
			printf("MS1022 init success.\n");
		}
    SPI_WriteCommand(0x70);
    //SPI_WriteCommand(0x01);
}

void MS1022_NewMeasure() {
	SPI_WriteCommand(0x70);
}

unsigned long MS1022_DoMeasure(unsigned char *pTimeoutFlag, unsigned char *pNoIntFlag)
{
	uint16_t	status;
	unsigned long ret = -(1u<<30);
	*pTimeoutFlag = 0;
	*pNoIntFlag = 0;
	
	status = SPI_ReadStatus(0xB4);
	//printf("read status %x\n",status);
	if(status & 0x10)	// timeout flags are 0
	//if(1)
	{
		*pTimeoutFlag = 0;
		//uint8_t t = 0xB0 | ((status & 0xF)-1);
		ret = SPI_ReadReg(0xB0);
		//printf("%ld\n",result>>15);
		//tmp = result & 0x7FFF;
		//result = result>>15;
		//ret = result + tmp/32768.0;
		//printf("%d %d t=%x\n",ret>>16, ret & 0xFFFF, t);
		return ret;
	}
	else	// timeout error process
	{
		*pTimeoutFlag = 1;
		return(ret);
	}
}

